package com.mlizhi.widgets.wave;



import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.Build;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;

import com.mlizhi.kingdom.R;


/**
 * 
 * @author Troy Lee
 * 将计算机系统坐标系转移为自定义坐标系，以圆心为原点（0,0）的坐标系。
 * 
 * 水波函数： y=Asin(ωx+φ)+k
 *
 */
public class CircularView extends View {
	
	
	private Context context;
	//背景圆所在的区域
    private final RectF mCircleBounds = new RectF();

    //底层大圆的画笔
    private Paint mBackgroundColorPaint = null;
    //底层大圆边宽
    private int mCircleStrokeWidth = 10;
    private int mGravity = Gravity.CENTER;
    //Horizontal的内边界技术依赖于mGravity
    private int mHorizontalInset = 0;
    //Vertical的内边界技术依赖于mGravity
    private int mVerticalInset = 0;
    //所有属性设置完成为true，此时在Layout View时候将不会发生错误
    private boolean mIsInitializing = true;
    //thumb是否可见
    private boolean mIsThumbEnabled = true;
    //thumb沿着底层圆转的进度
    private float mProgress = 0.0f;
    //thumb沿着底层圆转前的路径颜色
    private int mProgressBackgroundColor;
    //thumb沿着底层圆转后留下的路径颜色
    private int mProgressColor;
    //thumb沿着底层圆转所用的画笔
    private Paint mProgressColorPaint;
    //底层大圆的半径
    private float mRadius;
    //上一次大圆半径
    private float mLastRadius;
    //thumb的画笔
    private Paint mThumbColorPaint = null;
    //thumb的坐标 x
    private float mThumbPosX;
    //thumb的坐 y
    private float mThumbPosY;
    //thumb的半径
    private int mThumbRadius = 20;
    //我们用自己坐标系统的变化偏移量X
    private float mTranslationOffsetX;
    //我们用自己坐标系统的变化偏移量Y
    private float mTranslationOffsetY;
    //Thumb的路径
    private Path mPath = new Path(); 
    //Thumb 所要的bitmap
    private Bitmap ballBitmap;
    //**************水波的开始
    
    protected static final int LARGE = 1;
    protected static final int MIDDLE = 2;
    protected static final int LITTLE = 3;
    
    private final int WAVE_HEIGHT_LARGE = 16;
    private final int WAVE_HEIGHT_MIDDLE = 8;
    private final int WAVE_HEIGHT_LITTLE = 5;

    private final float WAVE_LENGTH_MULTIPLE_LARGE = 1.5f;
    private final float WAVE_LENGTH_MULTIPLE_MIDDLE = 1f;
    private final float WAVE_LENGTH_MULTIPLE_LITTLE = 0.5f;

    private final float WAVE_HZ_FAST = 0.13f;
    private final float WAVE_HZ_NORMAL = 0.09f;
    private final float WAVE_HZ_SLOW = 0.05f;

    public final int DEFAULT_ABOVE_WAVE_ALPHA = 200;
    public final int DEFAULT_BLOW_WAVE_ALPHA = 50;
    
    private Path mAboveWavePath = new Path();
    private Path mBlowWavePath = new Path();


    //上边水波画笔
    private Paint mAboveWavePaint;
    //下边水波画笔
    private Paint mBlowWavePaint;
    
    //画水区域的左、右和下边界
    private int left, right, bottom;
    // ω
    private double omega;
    //mWaveMultiple 和 mWaveLength来确定波长
    private float mWaveMultiple = WAVE_LENGTH_MULTIPLE_LITTLE;
    private float mWaveLength;
    //振幅
    private int mWaveHeight = WAVE_HEIGHT_MIDDLE;
    //波的右边界值（左边界为-mMaxRight）
    private float mMaxRight;
    //水平速度
    private float mWaveHz = WAVE_HZ_SLOW;
    private final float X_SPACE = 10;
    private final double PI2 = 2 * Math.PI;
    
    // 画水波的动画偏移量
    private float mAboveOffset = 0.0f;
    private float mBlowOffset  = mWaveHeight * 0.4f;
//    private PaintFlagsDrawFilter pdf = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);
  //**************水波结束

    public CircularView(Context context) {
    	super(context);
    }

    public CircularView(Context context, AttributeSet attrs) {
//        super(context, attrs);
        this(context, attrs, R.attr.circularStyle);
    }
   
    public CircularView(Context context, AttributeSet attrs,int defStyle) {
    	super(context, attrs, defStyle);
    	this.context = context;
    	 // load the styled attributes and set their properties
//        final TypedArray attributes = context.obtainStyledAttributes(attrs,R.styleable.CircularView);
    	final TypedArray attributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CircularView, defStyle, 0);
        if (attributes != null) {
            try {
                setProgressColor(attributes.getColor(R.styleable.CircularView_progress_color, Color.CYAN));
                setProgressBackgroundColor(attributes.getColor(R.styleable.CircularView_progress_background_color,Color.GREEN));
                setProgress(attributes.getFloat(R.styleable.CircularView_progress, 0.0f));
                setWheelSize((int) attributes.getDimension(R.styleable.CircularView_stroke_width, 10));
                setThumbEnabled(attributes.getBoolean(R.styleable.CircularView_thumb_visible, true));
                setWaveHeight(attributes.getInt(R.styleable.CircularView_wave_height, MIDDLE));
                setWaveMultiple(attributes.getInt(R.styleable.CircularView_wave_length, LITTLE));
                setWaveHz(attributes.getInt(R.styleable.CircularView_wave_hz, LITTLE));
                mGravity = attributes.getInt(R.styleable.CircularView_android_gravity,Gravity.CENTER);
            } finally {
                // make sure recycle is always called.
                attributes.recycle();
            }
        }

        mThumbRadius = mCircleStrokeWidth * 2;
        mBackgroundColorPaint = new Paint();
        mThumbColorPaint = new Paint();
        updateBackgroundColor();
        updateProgressColor();
        ballBitmap = BitmapFactory.decodeStream(getResources().openRawResource(R.raw.ic_detection_track));
        ballBitmap = toSmallImg(ballBitmap);
        initializePainters();
        // 初始化已经完成。
        mIsInitializing = false;
    }
    

	 private Bitmap toSmallImg(Bitmap bitmap) {
	 	  Matrix matrix = new Matrix(); 
	 	  matrix.postScale(1.2f,1.2f); //长和宽放大缩小的比例
	 	  Bitmap resizeBmp = Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);
	 	  return resizeBmp;
	 }
 

   
    
    /**
     * 初始化水波浪画笔
     */
    public void initializePainters() {
    	mAboveWavePaint = new Paint();
        mAboveWavePaint.setAlpha(DEFAULT_ABOVE_WAVE_ALPHA);
        mAboveWavePaint.setColor(context.getResources().getColor(R.color.theme_second_blue));
        mAboveWavePaint.setStyle(Paint.Style.FILL);
        mAboveWavePaint.setAntiAlias(true);

        mBlowWavePaint = new Paint();
        mBlowWavePaint.setColor(context.getResources().getColor(R.color.theme_second_blue));
        mBlowWavePaint.setAlpha(DEFAULT_BLOW_WAVE_ALPHA);
        mBlowWavePaint.setStyle(Paint.Style.FILL);
        mBlowWavePaint.setAntiAlias(true);
        
    }


	@SuppressLint("DrawAllocation")
	@Override
    protected void onDraw(final Canvas canvas) {
		
        canvas.translate(mTranslationOffsetX, mTranslationOffsetY);
//        calculatePath();
        // 画背景圆
        canvas.drawArc(mCircleBounds, 270, 360, false,mBackgroundColorPaint);
        canvas.save();
//        canvas.setDrawFilter(pdf);  
        //画水波浪线
        mPath.reset();
        canvas.clipPath(mPath); // makes the clip empty
//        canvas.clipPath(mPath, Region.Op.REPLACE);
        //遮罩层
        mPath.addCircle(0f, 0f, mRadius, Path.Direction.CW);
        canvas.clipPath(mPath, Region.Op.REPLACE);
        canvas.drawPath(mBlowWavePath, mBlowWavePaint);
        canvas.drawPath(mAboveWavePath, mAboveWavePaint);
        
        
        // 重新画背景圆
        canvas.drawArc(mCircleBounds, 270, 360, false,mBackgroundColorPaint);
        canvas.restore();
        
        //画Thumb进度
        if (isThumbEnabled()) {
        	final float progressRotation = getCurrentRotation();
        	// 根据进度画thumb图标转的路径
        	canvas.drawArc(mCircleBounds, 270, progressRotation, false,mProgressColorPaint);
        	//save()作用：在save()方法之前的全都保存，在save()方法之后，restore()方法之前的都清空。
        	canvas.save();
            // 将thumb图标初始位置放到0度
            canvas.rotate(progressRotation - 90);
            //设置thumb图标为小球
            canvas.drawBitmap(ballBitmap, mThumbPosX-ballBitmap.getWidth()/2f, mThumbPosY - ballBitmap.getHeight()/2f, mThumbColorPaint);
            canvas.restore();
        }
        if(mLastRadius != mRadius) {
        	mLastRadius = mRadius;
        	startWave();
        }
    }

    @Override
    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
        final int height = getDefaultSize(getSuggestedMinimumHeight() + getPaddingTop() + getPaddingBottom() ,heightMeasureSpec);
        final int width = getDefaultSize(getSuggestedMinimumWidth() + getPaddingLeft() + getPaddingRight(), widthMeasureSpec);

        //所要画出圆形的目标直径
        final int diameter;
        if (heightMeasureSpec == MeasureSpec.UNSPECIFIED) { // ScrollView
            diameter = width;
            computeInsets(0, 0);
        } else if (widthMeasureSpec == MeasureSpec.UNSPECIFIED) { // HorizontalScrollView
            diameter = height;
            computeInsets(0, 0);
        } else {// 默认
            diameter = Math.min(width, height);
            computeInsets(width - diameter, height - diameter);
        }
        setMeasuredDimension(diameter, diameter);
        final float halfDiameter = diameter * 0.5f;
        // 所画圆形的边宽
        final float drawedWith;
        if (isThumbEnabled()) {
            drawedWith = mThumbRadius * (5f / 6f);
        } else {
//            drawedWith = mCircleStrokeWidth / 2f;
        	drawedWith = mCircleStrokeWidth;
        }
        // 所要画圆形的半径;-10.5f 是为了更好的融入到RectF中，起到padding的作用
        mRadius = halfDiameter - drawedWith - 10.5f;
        
        //在自定义坐标系中确定背景区域
        mCircleBounds.set(-mRadius, -mRadius, mRadius, mRadius);
        // Thumb的初始位置
        mThumbPosX = (float) (mRadius * Math.cos(0));
        mThumbPosY = (float) (mRadius * Math.sin(0));
        // 坐标偏移量
        mTranslationOffsetX = halfDiameter + mHorizontalInset;
        mTranslationOffsetY = halfDiameter + mVerticalInset;

    }
    
    


    public int getCircleStrokeWidth() {
        return mCircleStrokeWidth;
    }


    public float getProgress() {
        return mProgress;
    }

    public int getProgressColor() {
        return mProgressColor;
    }

    public boolean isThumbEnabled() {
        return mIsThumbEnabled;
    }

	public void setProgress(final float progress) {

		if (progress >= 1.0f) {
			mProgress = 1.0f;
		} else {
			mProgress = progress % 1.0f;
		}
		calculatePath();
		invalidate();

	}

    @Override
    public void onWindowFocusChanged(boolean hasWindowFocus) {
        super.onWindowFocusChanged(hasWindowFocus);
        if (hasWindowFocus) {
            if (mWaveLength == 0) {
                startWave();
            }
        }
    }
	
    public void setProgressBackgroundColor(final int color) {
        mProgressBackgroundColor = color;
        updateBackgroundColor();
    }

    public void setProgressColor(final int color) {
        mProgressColor = color;
        updateProgressColor();
    }

    public void setThumbEnabled(final boolean enabled) {
        mIsThumbEnabled = enabled;
    }

    public void setWheelSize(final int dimension) {
        mCircleStrokeWidth = dimension;

        // update the paints
        updateBackgroundColor();
        updateProgressColor();
    }

    /**
     * Compute insets.
     *
     * <pre>
     *  ______________________
     * |_________dx/2_________|
     * |......| /'''''\|......|
     * |-dx/2-|| View ||-dx/2-|
     * |______| \_____/|______|
     * |________ dx/2_________|
     * </pre>
     *
     * @param dx the dx the horizontal unfilled space
     * @param dy the dy the horizontal unfilled space
     */
    @SuppressLint("NewApi")
	private void computeInsets(final int dx, final int dy) {
        int absoluteGravity = mGravity;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            absoluteGravity = Gravity.getAbsoluteGravity(mGravity, getLayoutDirection());
        }

        switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
            case Gravity.LEFT:
                mHorizontalInset = 0;
                break;
            case Gravity.RIGHT:
                mHorizontalInset = dx;
                break;
            case Gravity.CENTER_HORIZONTAL:
            default:
                mHorizontalInset = dx / 2;
                break;
        }
        switch (absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK) {
            case Gravity.TOP:
                mVerticalInset = 0;
                break;
            case Gravity.BOTTOM:
                mVerticalInset = dy;
                break;
            case Gravity.CENTER_VERTICAL:
            default:
                mVerticalInset = dy / 2;
                break;
        }
    }

    /**
     *根据进度获取当前旋转的度数
     */
    private float getCurrentRotation() {
        return 360f * mProgress;
    }


    private void updateBackgroundColor() {
        mBackgroundColorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBackgroundColorPaint.setColor(mProgressBackgroundColor);
        mBackgroundColorPaint.setStyle(Paint.Style.STROKE);
        mBackgroundColorPaint.setStrokeWidth(mCircleStrokeWidth);

        invalidate();
    }


    /**
     * updates the paint of the progress and the thumb to give them a new visual style
     */
    private void updateProgressColor() {
        mProgressColorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mProgressColorPaint.setColor(mProgressColor);
        mProgressColorPaint.setStyle(Paint.Style.STROKE);
        mProgressColorPaint.setStrokeWidth(mCircleStrokeWidth);

        mThumbColorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mThumbColorPaint.setColor(mProgressColor);
        mThumbColorPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mThumbColorPaint.setStrokeWidth(mCircleStrokeWidth);

        invalidate();
    }

	private void setWaveMultiple(int size) {
		switch (size) {
		case LARGE:
			mWaveMultiple = WAVE_LENGTH_MULTIPLE_LARGE;
			break;
		case MIDDLE:
			mWaveMultiple = WAVE_LENGTH_MULTIPLE_MIDDLE;
			break;
		case LITTLE:
			mWaveMultiple = WAVE_LENGTH_MULTIPLE_LITTLE;
			break;
		default:
			mWaveMultiple = WAVE_LENGTH_MULTIPLE_LITTLE;
			break;
		}
//		mWaveMultiple = DensityUtil.dip2px(context, mWaveMultiple);
	}

	private void setWaveHeight(int size) {
		switch (size) {
		case LARGE:
			mWaveHeight = WAVE_HEIGHT_LARGE;
			break;
		case MIDDLE:
			mWaveHeight = WAVE_HEIGHT_MIDDLE;
			break;
		case LITTLE:
			mWaveHeight = WAVE_HEIGHT_LITTLE;
			break;
		default:
			mWaveHeight = WAVE_HEIGHT_LITTLE;
			break;
		}
//		mWaveHeight = DensityUtil.dip2px(context, mWaveHeight);
	}

	private void setWaveHz(int size) {
		switch (size) {
		case LARGE:
			mWaveHz = WAVE_HZ_FAST;
			break;
		case MIDDLE:
			mWaveHz = WAVE_HZ_NORMAL;
			break;
		case LITTLE:
			mWaveHz = WAVE_HZ_SLOW;
			break;
		default:
			mWaveHz = WAVE_HZ_SLOW;
			break;
		}
//		mWaveHz = DensityUtil.dip2px(context, mWaveHz);
	}

    /**
     * 水波的路径
     */
    private void calculatePath() {
        mAboveWavePath.reset();
        mBlowWavePath.reset();
        getWaveOffset();
        float y;
        mAboveWavePath.moveTo(left, bottom);
        for (float x = -mMaxRight; x <= mMaxRight ; x += X_SPACE) {
            y = (float) (mWaveHeight * Math.sin(omega * x + mAboveOffset) + mWaveHeight) + mRadius/5;
            mAboveWavePath.lineTo(x, y);
        }
        mAboveWavePath.lineTo(right, bottom);

        mBlowWavePath.moveTo(left, bottom);
        for (float x = -mMaxRight; x <= mMaxRight; x += X_SPACE) {
            y = (float) (mWaveHeight * Math.sin(omega * x + mBlowOffset) + mWaveHeight) + mRadius/5;
            mBlowWavePath.lineTo(x, y);
        }
        mBlowWavePath.lineTo(right, bottom);
    	
    }
    
    /**
     * 开始画，主要就是赋初值
     */
    public void startWave() {
        if (getWidth() != 0) {
            int width = getWidth();
            mWaveLength = width * mWaveMultiple;
			// left = -getRight();
			// right = getRight();
			bottom = getBottom();
			// mMaxRight = right + X_SPACE;
            left = (int) -mRadius;
            right = (int) mRadius;
            mMaxRight = (int)mRadius;
            omega = PI2 / mWaveLength;
            calculatePath();
            invalidate();
        }
    }
    /**
     * 获取上下水波的偏移量
     */
    private void getWaveOffset() {
        if (mBlowOffset > Float.MAX_VALUE - 100) {
            mBlowOffset = 0;
        } else {
            mBlowOffset += mWaveHz;
        }

        if (mAboveOffset > Float.MAX_VALUE - 100) {
            mAboveOffset = 0;
        } else {
            mAboveOffset += mWaveHz;
        }
    }
	//**************水波的结束
    
    
}
